"""
认证路由
用户注册、登录、权限管理
"""

from typing import Optional
import uuid
from datetime import timedelta
from fastapi import APIRouter, Depends, HTTPException, status as status_module
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from sqlalchemy.orm import Session as DBSession

from src.config.database import get_db
from src.config.settings import settings
from src.models.user import User, UserCreate, UserResponse, Token, UserLogin
from src.services.auth_service import (
    AuthService, get_current_active_user, get_current_active_user_dep,
    require_agent_or_admin, require_admin
)
from src.utils.logging import get_logger

logger = get_logger(__name__)

# 定义OAuth2密码流
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login")

router = APIRouter(prefix="/auth", tags=["auth"])


@router.post("/register", response_model=UserResponse)
async def register_user(
    user_data: UserCreate,
    db: DBSession = Depends(get_db)
):
    """用户注册"""
    from src.exceptions import ValidationError
    
    # 检查用户名是否已存在
    existing_user = AuthService.get_user_by_username(db, user_data.username)
    if existing_user:
        raise ValidationError(message="用户名已存在", field="username")
    
    # 检查邮箱是否已存在
    existing_email = AuthService.get_user_by_email(db, user_data.email)
    if existing_email:
        raise ValidationError(message="邮箱已存在", field="email")
    
    # 创建用户
    user = AuthService.create_user(db, user_data)
    return UserResponse.from_orm(user)


@router.post("/login", response_model=Token)
async def login(
    form_data: OAuth2PasswordRequestForm = Depends(),
    db: DBSession = Depends(get_db)
):
    """用户登录"""
    try:
        from src.models.user import UserLogin
        # 直接使用AuthService.login_user方法处理登录逻辑
        login_data = UserLogin(
            username=form_data.username,
            password=form_data.password
        )
        return AuthService.login_user(db, login_data)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"用户登录失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="用户登录失败"
        )


@router.get("/me", response_model=UserResponse)
async def get_current_user(
    current_user: User = Depends(get_current_active_user_dep)
):
    """获取当前用户信息"""
    return UserResponse.from_orm(current_user)


@router.get("/users", response_model=list[UserResponse])
async def get_users(
    skip: int = 0,
    limit: int = 100,
    role: Optional[str] = None,
    status: Optional[str] = None,
    current_user: User = Depends(require_admin),
    db: DBSession = Depends(get_db)
):
    """获取用户列表（仅管理员）"""
    try:
        users = AuthService.get_users(db, skip, limit, role, status)
        return [UserResponse.from_orm(user) for user in users]
    except Exception as e:
        logger.error(f"获取用户列表失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户列表失败"
        )


@router.get("/users/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: uuid.UUID,
    current_user: User = Depends(require_admin),
    db: DBSession = Depends(get_db)
):
    """获取用户详情（仅管理员）"""
    try:
        user = AuthService.get_user_by_id(db, user_id)
        if not user:
            raise HTTPException(
                status_code=status_module.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        return UserResponse.from_orm(user)
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取用户详情失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户详情失败"
        )


@router.put("/users/{user_id}/role")
async def update_user_role(
    user_id: uuid.UUID,
    role: str,
    current_user: User = Depends(require_admin),
    db: DBSession = Depends(get_db)
):
    """更新用户角色（仅管理员）"""
    try:
        if role not in ["user", "agent", "admin"]:
            raise HTTPException(
                status_code=status_module.HTTP_400_BAD_REQUEST,
                detail="角色必须是 user、agent 或 admin"
            )
        
        user = AuthService.get_user_by_id(db, user_id)
        if not user:
            raise HTTPException(
                status_code=status_module.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        updated_user = AuthService.update_user_role(db, user, role)
        return {
            "message": "用户角色更新成功",
            "user": UserResponse.from_orm(updated_user)
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新用户角色失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新用户角色失败"
        )


@router.put("/users/{user_id}/status")
async def update_user_status(
    user_id: uuid.UUID,
    status: str,
    current_user: User = Depends(require_admin),
    db: DBSession = Depends(get_db)
):
    """更新用户状态（仅管理员）"""
    try:
        if status not in ["active", "inactive"]:
            raise HTTPException(
                status_code=status_module.HTTP_400_BAD_REQUEST,
                detail="状态必须是 active 或 inactive"
            )
        
        user = AuthService.get_user_by_id(db, user_id)
        if not user:
            raise HTTPException(
                status_code=status_module.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        updated_user = AuthService.update_user_status(db, user, status)
        return {
            "message": "用户状态更新成功",
            "user": UserResponse.from_orm(updated_user)
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新用户状态失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新用户状态失败"
        )


@router.post("/refresh", response_model=Token)
async def refresh_token(
    refresh_token: str,
    db: DBSession = Depends(get_db)
):
    """刷新访问令牌"""
    try:
        return AuthService.refresh_access_token(refresh_token)
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"刷新令牌失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="刷新令牌失败"
        )


@router.post("/logout")
async def logout(
    token: str = Depends(oauth2_scheme),
    current_user: User = Depends(get_current_active_user_dep)
):
    """用户登出"""
    try:
        # 撤销当前令牌
        AuthService.revoke_token(token)
        return {"message": "成功登出"}
    except Exception as e:
        logger.error(f"用户登出失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="登出失败"
        )


@router.post("/password/reset")
async def reset_password(
    username: str,
    db: DBSession = Depends(get_db)
):
    """重置密码（发送重置邮件）"""
    try:
        user = AuthService.get_user_by_username(db, username)
        if not user:
            # 出于安全考虑，不透露用户是否存在
            return {"message": "如果用户存在，重置邮件已发送"}
        
        # 这里应该实现发送重置邮件的逻辑
        # 生成重置令牌并发送邮件
        
        return {"message": "重置邮件已发送"}
    except Exception as e:
        logger.error(f"重置密码失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="重置密码失败"
        )


@router.post("/password/change")
async def change_password(
    current_password: str,
    new_password: str,
    current_user: User = Depends(get_current_active_user_dep),
    db: DBSession = Depends(get_db)
):
    """修改密码"""
    try:
        # 验证当前密码
        if not AuthService.verify_password(current_password, str(current_user.password_hash)):
            raise HTTPException(
                status_code=status_module.HTTP_401_UNAUTHORIZED,
                detail="当前密码错误"
            )
        
        # 更新密码
        updated_user = AuthService.update_password(db, current_user, new_password)
        return {
            "message": "密码修改成功",
            "user": UserResponse.from_orm(updated_user)
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"修改密码失败: {e}")
        raise HTTPException(
            status_code=status_module.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="修改密码失败"
        )
